#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
微信小程序后端服务
集成ERNIE大模型的智能对话系统
"""

import os
import json
import logging
import hashlib
import time
from datetime import datetime
from flask import Flask, request, jsonify, render_template, send_from_directory
from flask_cors import CORS
import requests
from werkzeug.utils import secure_filename

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('logs/app.log', encoding='utf-8'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

app = Flask(__name__)
CORS(app)

# 配置
app.config['SECRET_KEY'] = 'your-secret-key-here'
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB max file size

# 确保必要的目录存在
os.makedirs('logs', exist_ok=True)
os.makedirs('uploads', exist_ok=True)
os.makedirs('static/images', exist_ok=True)

# 微信小程序配置
WECHAT_CONFIG = {
    'app_id': 'your_app_id',
    'app_secret': 'your_app_secret',
    'token': 'your_token'
}

# ERNIE模型配置
ERNIE_CONFIG = {
    'api_key': 'your_ernie_api_key',
    'secret_key': 'your_ernie_secret_key',
    'model_path': './ERNIE-4.5-0.3B-Paddle'
}

class ERNIEService:
    """ERNIE大模型服务类"""
    
    def __init__(self):
        self.access_token = None
        self.token_expires = 0
        
    def get_access_token(self):
        """获取百度API访问令牌"""
        if self.access_token and time.time() < self.token_expires:
            return self.access_token
            
        url = "https://aip.baidubce.com/oauth/2.0/token"
        params = {
            "grant_type": "client_credentials",
            "client_id": ERNIE_CONFIG['api_key'],
            "client_secret": ERNIE_CONFIG['secret_key']
        }
        
        try:
            response = requests.post(url, params=params)
            result = response.json()
            
            if 'access_token' in result:
                self.access_token = result['access_token']
                self.token_expires = time.time() + result.get('expires_in', 3600) - 300
                return self.access_token
            else:
                logger.error(f"获取access_token失败: {result}")
                return None
        except Exception as e:
            logger.error(f"获取access_token异常: {e}")
            return None
    
    def chat(self, message, history=None):
        """与ERNIE模型对话"""
        access_token = self.get_access_token()
        if not access_token:
            return {"error": "无法获取访问令牌"}
        
        url = f"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-4.0-8k?access_token={access_token}"
        
        messages = []
        if history:
            messages.extend(history)
        messages.append({"role": "user", "content": message})
        
        payload = {
            "messages": messages,
            "temperature": 0.7,
            "top_p": 0.8,
            "penalty_score": 1.0
        }
        
        try:
            response = requests.post(url, json=payload)
            result = response.json()
            
            if 'result' in result:
                return {
                    "success": True,
                    "response": result['result'],
                    "usage": result.get('usage', {})
                }
            else:
                logger.error(f"ERNIE API错误: {result}")
                return {"error": "模型响应异常"}
        except Exception as e:
            logger.error(f"ERNIE API异常: {e}")
            return {"error": "网络请求失败"}

class WeChatService:
    """微信小程序服务类"""
    
    @staticmethod
    def verify_signature(signature, timestamp, nonce):
        """验证微信签名"""
        token = WECHAT_CONFIG['token']
        tmp_arr = [token, timestamp, nonce]
        tmp_arr.sort()
        tmp_str = ''.join(tmp_arr)
        tmp_str = hashlib.sha1(tmp_str.encode('utf-8')).hexdigest()
        return tmp_str == signature
    
    @staticmethod
    def get_user_info(code):
        """通过code获取用户信息"""
        # 获取access_token
        url = "https://api.weixin.qq.com/sns/jscode2session"
        params = {
            'appid': WECHAT_CONFIG['app_id'],
            'secret': WECHAT_CONFIG['app_secret'],
            'js_code': code,
            'grant_type': 'authorization_code'
        }
        
        try:
            response = requests.get(url, params=params)
            return response.json()
        except Exception as e:
            logger.error(f"获取用户信息失败: {e}")
            return {"error": "获取用户信息失败"}

# 初始化服务
ernie_service = ERNIEService()
wechat_service = WeChatService()

@app.route('/')
def index():
    """首页"""
    return render_template('index.html')

@app.route('/api/health')
def health_check():
    """健康检查"""
    return jsonify({
        "status": "healthy",
        "timestamp": datetime.now().isoformat(),
        "version": "1.0.0"
    })

@app.route('/api/wechat/verify', methods=['GET', 'POST'])
def wechat_verify():
    """微信服务器验证"""
    if request.method == 'GET':
        signature = request.args.get('signature')
        timestamp = request.args.get('timestamp')
        nonce = request.args.get('nonce')
        echostr = request.args.get('echostr')
        
        if wechat_service.verify_signature(signature, timestamp, nonce):
            return echostr
        else:
            return 'Invalid signature', 403
    
    # POST请求处理微信消息
    return jsonify({"status": "ok"})

@app.route('/api/wechat/login', methods=['POST'])
def wechat_login():
    """微信小程序登录"""
    data = request.get_json()
    code = data.get('code')
    
    if not code:
        return jsonify({"error": "缺少code参数"}), 400
    
    user_info = wechat_service.get_user_info(code)
    
    if 'openid' in user_info:
        # 这里可以保存用户信息到数据库
        return jsonify({
            "success": True,
            "openid": user_info['openid'],
            "session_key": user_info.get('session_key')
        })
    else:
        return jsonify({"error": "登录失败"}), 400

@app.route('/api/chat', methods=['POST'])
def chat():
    """智能对话接口"""
    data = request.get_json()
    message = data.get('message', '').strip()
    history = data.get('history', [])
    
    if not message:
        return jsonify({"error": "消息不能为空"}), 400
    
    # 记录用户消息
    logger.info(f"用户消息: {message}")
    
    # 调用ERNIE模型
    result = ernie_service.chat(message, history)
    
    if result.get('success'):
        logger.info(f"AI回复: {result['response']}")
        return jsonify({
            "success": True,
            "response": result['response'],
            "usage": result.get('usage', {}),
            "timestamp": datetime.now().isoformat()
        })
    else:
        return jsonify({"error": result.get('error', '未知错误')}), 500

@app.route('/api/upload', methods=['POST'])
def upload_file():
    """文件上传接口"""
    if 'file' not in request.files:
        return jsonify({"error": "没有文件"}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({"error": "文件名为空"}), 400
    
    if file:
        filename = secure_filename(file.filename)
        timestamp = str(int(time.time()))
        filename = f"{timestamp}_{filename}"
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        
        try:
            file.save(filepath)
            file_url = f"/uploads/{filename}"
            
            return jsonify({
                "success": True,
                "filename": filename,
                "url": file_url,
                "size": os.path.getsize(filepath)
            })
        except Exception as e:
            logger.error(f"文件上传失败: {e}")
            return jsonify({"error": "文件上传失败"}), 500

@app.route('/uploads/<filename>')
def uploaded_file(filename):
    """访问上传的文件"""
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

@app.route('/api/stats')
def get_stats():
    """获取系统统计信息"""
    try:
        # 统计上传文件数量
        upload_count = len([f for f in os.listdir('uploads') if os.path.isfile(os.path.join('uploads', f))])
        
        # 统计日志文件大小
        log_size = 0
        if os.path.exists('logs/app.log'):
            log_size = os.path.getsize('logs/app.log')
        
        return jsonify({
            "upload_count": upload_count,
            "log_size": log_size,
            "model_status": "active",
            "uptime": time.time()
        })
    except Exception as e:
        logger.error(f"获取统计信息失败: {e}")
        return jsonify({"error": "获取统计信息失败"}), 500

@app.errorhandler(404)
def not_found(error):
    """404错误处理"""
    return jsonify({"error": "接口不存在"}), 404

@app.errorhandler(500)
def internal_error(error):
    """500错误处理"""
    logger.error(f"内部服务器错误: {error}")
    return jsonify({"error": "内部服务器错误"}), 500

if __name__ == '__main__':
    logger.info("启动微信小程序后端服务...")
    app.run(host='0.0.0.0', port=5000, debug=True)